import random

from django.conf import settings
from django.http import JsonResponse
from rest_framework.generics import CreateAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from django_redis import get_redis_connection
from rest_framework_extensions.cache.mixins import CacheResponseMixin
from rest_framework_jwt.views import ObtainJSONWebToken

from celery_tasks.sms.task import send_sms_code
from celery_tasks.sms.yuntongxun.sms import CCP
from itsdangerous import TimedJSONWebSignatureSerializer as TJS

# Create your views here.
from users.models import User
from users.serializers import UserSerializer, UserDetailSerializer, UserUpdateSerializer
from users.utils import merge_cart_cookie_to_redis
from django.shortcuts import HttpResponse
from meiduo.utils.captcha import captcha



class SmsCodeView(APIView):
    def get(self, request, mobile):
        conn = get_redis_connection('sms_session')
        flag = conn.get('mobile_flag_%s' % mobile)
        if flag:
            return Response({'massage': '先森，你的要求很频繁腻～'})

        # 生成验证码
        sms_code = '%06d' % random.randint(0, 999999)
        print(sms_code)

        pl = conn.pipeline()
        pl.setex('mobile_%s' % mobile, 300, sms_code)
        pl.setex('mobile_flag_%s' % mobile, 60, sms_code)
        pl.execute()

        send_sms_code.delay(mobile, sms_code, 60)

        return Response({'massage': 'ok'})


class MobilesView(APIView):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile)

        return Response({'count': count})


class UsernameView(APIView):
    def get(self, request, username):
        count = User.objects.filter(username=username)

        return Response({'count': count})


class UserView(CreateAPIView):
    serializer_class = UserSerializer


class UserDetailView(RetrieveAPIView):
    serializer_class = UserDetailSerializer
    permission_classes = [IsAuthenticated]  # 权限指定

    def get_object(self):
        return self.request.user


class UserUpdateView(UpdateAPIView):
    serializer_class = UserUpdateSerializer

    def get_object(self):
        return self.request.user

class ModifyPasswordView(APIView):
    """
    修改密码
    old_password: vm.old_pwd,
    password: vm.new_pwd,
    password2: vm.new_cpwd
    """
    def put(self,request,pk):
        data=request.data
        user = User.objects.get(id=pk)
        if not user.check_password(data['old_password']):
            raise Exception({'message':'原密码输入错误'})
        if data['password'] != data['password2']:
            raise Exception({'message':'输入新密码不一致'})
        if data['old_password'] == data['password']:
            raise Exception({'message':'新密码与旧密码不能一致'})
        user.set_password(data['password'])
        user.save()
        return Response({'message':'ok'})



class EmailVerifyView(CacheResponseMixin, APIView):

    def get(self, request):
        token = request.query_params.get('token')
        tjs = TJS(settings.SECRET_KEY, 300)
        try:
            data = tjs.loads(token)
        except:
            return Response({'error': '邮件验证失败'}, status=400)

        username = data['name']
        try:
            user = User.objects.get(username=username)
        except:
            return Response({'error': '没有这个沙雕用户'}, status=400)

        user.email_active = True
        user.save()

        return Response({'massage': True})


class UserLoginView(ObtainJSONWebToken):

    def post(self, request, *args, **kwargs):
        response = super().post(request, *args, **kwargs)

        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            user = serializer.object.get('user') or request.user
            # 合并购物车
            response = merge_cart_cookie_to_redis(request, user, response)

        return response


class CheckImage(APIView):
    """
    检验图片验证码
    """

    def get(self, request, username):
        # 获取前端传入的参数
        text = request.query_params.get('text')
        uuid = request.query_params.get('image_code_id')

        # 判断用户名是否存在
        try:
            user = User.objects.filter(username=username)
        except:
            user = User.objects.filter(mobile=username)
            if not user:
                return Response({'error': '用户名或手机号不存在'}, status=404)
        # 获取ｒｅｄｉｓ数据库中的图片验证码
        mobile = user.mobile
        conn = get_redis_connection('image_code')
        real_text = conn.get('image_code_%s' % uuid).decode()
        if not real_text.lower() == text.lower():
            return Response({'error': '图片验证码错误'}, status=400)
        # 生成加密后的token数据
        tjs = TJS(settings.SECRET_KEY, 300)
        access_token = tjs.dumps({'mobile': mobile}).decode()

        # 把token存储在ｒｅｄｉｓ中
        token = get_redis_connection('access_token')
        # 以ｓｔｒｉｎｇ类型写入ｒｅｄｉｓ中
        token.setex('mobile_%s' % mobile, 300, access_token)

        return JsonResponse({
            'mobile': mobile,
            'access_token': access_token
        })


class SendSmsCode(APIView):
    def get(self, request):
        # 获取到数据库中的access——token，进行解密，获取手机号
        access_token = request.query_params.get('access_token')
        tjs = TJS(settings.SECRET_KEY, 300)
        data = tjs.loads(access_token)
        mobile = data.get('mobile')
        # 1.建立redis链接对象
        conn = get_redis_connection('sms_code')
        flag = conn.get('sms_code_flag_%s' % mobile)
        if flag:
            return Response({'error': '请求过于频繁'}, status=400)
        # 2.生成短信验证码
        sms_code = '%06d' % random.randint(0, 999999)
        print(sms_code)
        # 3.保存验证码到缓存中
        # 建立链接redis对象
        conn = get_redis_connection('sms_code')
        # 管道用法
        pl = conn.pipeline()
        pl.setex('sms_code_%s' % mobile, 300, sms_code)
        pl.setex('sms_code_flag_%s' % mobile, 60, 1)
        # 连接redis缓存，传入写入指令
        pl.execute()
        # 使用celery发送短信
        send_sms_code.delay(mobile, sms_code)
        return Response({'mobile': mobile})


class SMSCode(APIView):
    def get(self, request, username):
        # 获取到数据库中用户的信息
        user = User.objects.get(username=username)
        mobile = user.mobile
        user_id = user.id
        sms_code = request.query_params.get('sms_code')
        # 获取redis中的短信验证码
        conn = get_redis_connection('sms_code')
        real_code = conn.get('sms_code_%s' % mobile).decode()
        # 判断短信验证码
        if not real_code == sms_code:
            return Response({'error': 'sms_code错误'}, status=400)
        # 将手机号进行加密
        tjs = TJS(settings.SECRET_KEY, 300)
        access_token = tjs.dumps({'mobile': mobile}).decode()
        # 结果返回
        return Response({'access_token': access_token,
                         'user_id': user_id
                         })


class ValidatePassword(CreateAPIView):
    def post(self, request, user_id):
        # 获取前端传入的密码
        data = request.data
        password = data['password']
        password2 = data['password2']
        # 　判断前端传入的两次密码
        if not password == password2:
            return Response({'errors': '密码不一致'}, status=400)
        # 将新的用户密码加密后保存到ｕｓｅｒ里面
        user = User.objects.get(id=user_id)
        user.set_password(password)
        # user.password = password
        user.save()
        # 返回数据
        return Response({'message': True})

class ImageCode(APIView):
    # 生成图片验证码
    def get(self, request, uuid):
        # 检查参数是传入,如果没传，直接return
        if not uuid:
            return Response({'errors': '无uuid值'}, status=400)
        # 调用captcha工具包,来生成图片验证码
        name, text, image = captcha.captcha.generate_captcha()
        # 在redis中存储图片验证码内容（text）
        conn = get_redis_connection('image_code')
        # string类型写入redis
        conn.setex('image_code_%s'%uuid, 300, text)
        # 返回前端图片，使用make_response(image)
        return HttpResponse(image, content_type='image.jpg')

